﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
using System;
using System.Xml.Serialization;
using System.ComponentModel;
using System.Runtime.Serialization;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BrainTechLLC.ThreadSafeObjects;

namespace BrainTechLLC
{
    [Serializable]
    [DataContract]
    public partial class SequenceOfModifications
    {
        [XmlIgnore, NonSerialized]
        protected object _applyToObject;

        [XmlIgnore]
        public object ApplyToObject { get { return _applyToObject; } set { _applyToObject = value; } }

        [DataMember]
        protected ThreadSafeQueue<Modification> _modificationsAndRequisites;

        [XmlIgnore]
        public ThreadSafeQueue<Modification> ModificationsAndRequisites
        {
            get
            {
                if (_modificationsAndRequisites == null)
                    Interlocked.CompareExchange<ThreadSafeQueue<Modification>>(ref _modificationsAndRequisites, new ThreadSafeQueue<Modification>(), null);

                return _modificationsAndRequisites;
            }
            set
            {
                _modificationsAndRequisites = value;
            }
        }

        public SequenceOfModifications() { }

        public void PerformChanges(object o)
        {
            Signals signals = new Signals();
            Modification c;
            while (ModificationsAndRequisites.Dequeue(out c))
            {
                if (c.PrerequisiteForChange == null || c.PrerequisiteForChange.Check(o, c.Change, signals))
                {
                    c.Change.ApplyChange(o, signals);
                }

                if (c.PostChangeCheck != null)
                    c.PostChangeCheck.Check(o, c.Change, signals);

                if (signals.AbortSubsequentChanges)
                    break;
            }
        }

        public void Execute(object applyTo)
        {
            if (!Cancelled)
            {
                _applyToObject = applyTo;
                PerformChanges(ApplyToObject);
            }
        }
    }

    public partial class SequenceOfModifications : IExecutableWorkItem
    {
        [XmlIgnore, NonSerialized]
        protected DateTime _executionTime;

        [XmlIgnore, NonSerialized]
        protected bool _cancelled;

        [XmlIgnore]
        public DateTime ExecutionTime { get { return _executionTime; } set { _executionTime = value; } }

        [XmlIgnore]
        public bool Cancelled { get { return _cancelled; } set { _cancelled = value; } }

        public void Execute()
        {
            if (!Cancelled)
                PerformChanges(ApplyToObject);
        }
    }
}
